#!/usr/bin/python


global_tools = { \
    '.c' : { \
        'exec'  : 'gcc',
        'flags' : '-c -g -fno-builtin -fno-stack-protector -O2 -m32',
        'inc'   : '-I__inc__',
        'direct': '__src__',
        'obj'   : '-o __obj__ __src__',
        'dep'   : '-MM __src__ > __dep__',
    },

    '.asm' : { \
        'exec'  : 'nasm',
        'flags' : '-f elf',
        'inc'   : '-i__inc__',
        'direct': '__src__',
        'obj'   : '-o __obj__ __src__',
        'dep'   : '-M __src__ > __dep__',
    },
    
    'ld' : { \
        'exec'  : 'ld',
        'flags' : '-m elf_i386 -s',
        'script': '-T __script__',
        'obj'   : '-o __target__ __obj__',
    },
    
    'ar' : { \
        'exec'  : 'ar',
        'flags' : 'crD',
        'obj'   : '__target__ __obj__',
    },
    
    'strip' : { \
        'exec'  : 'strip',
        'flags' : '',
        'obj'   : '__target__',
    },
    
    'gen_bin' : { \
        'exec'  : 'objcopy',
        'flags' : '-O binary',
        'obj'   : '__src__ __target__',
    },
}

boot_tools = { \
    '.c' : { \
        'exec'  : 'gcc',
        'flags' : '-c -fno-builtin -fno-stack-protector -O0 -m32 -fno-tree-loop-optimize',
        'inc'   : '-I__inc__',
        'direct': '__src__',
        'obj'   : '-o __obj__ __src__',
        'dep'   : '-MM __src__ > __dep__',
    },

    '.asm' : { \
        'exec'  : 'nasm',
        'flags' : '',
        'inc'   : '-i__inc__',
        'direct': '__src__',
        'obj'   : '-o __obj__ __src__',
        'dep'   : '-M __src__ > __dep__',
    },
    
    'ld' : { \
        'exec'  : 'ld',
        'flags' : '-m elf_i386 -s',
        'script': '-T __script__',
        'obj'   : '-o __target__ __obj__',
    },
}

def build_boot_fp():
    print_info('boot.fp', 'Building floppy boot')
    
    # Get files involved
    src_files = get_all_files(arch_dir + 'boot/floppy/', None)
    target_file = bin_dir + 'boot/tdlrboot.fp'
    
    # Aseembly start section
    direct_build_files(
        files = [ arch_dir + 'boot/floppy/boot.asm' ],
        target_name = obj_dir + 'boot/floppy/floppy.boot',
        ext_dep = None,
        tools = arch_tools['boot_tools']
    )
    
    # Floppy boot section
    build_files(
        files = [ arch_dir + 'boot/floppy/floppy.c' ],
        target_name = obj_dir + 'boot/floppy/floppy.elf',
        ext_dep = [ arch_dir + 'boot/floppy/floppy.ld' ],
        ext_flags = { 'ld/script' : arch_dir + 'boot/floppy/floppy.ld' },
        tools = arch_tools['boot_tools']
    )
    gen_bin(
        src_name = obj_dir + 'boot/floppy/floppy.elf',
        target_name = obj_dir + 'boot/floppy/floppy.bin',
        tools = arch_tools['boot_tools']
    )
    
    # Concatinate the sections
    cat_files(
        files = [ obj_dir + 'boot/floppy/floppy.boot', obj_dir + 'boot/floppy/floppy.bin' ],
        target_name = target_file,
        tools = arch_tools['boot_tools']
    )

def build_boot():
    if 'build_boot_fp' in arch_funcs:
        arch_funcs['build_boot_fp']()
        
    if 'build_boot_hd' in arch_funcs:
        arch_funcs['build_boot_hd']()
        
    if 'build_boot_cd' in arch_funcs:
        arch_funcs['build_boot_cd']()

def build_loader():
    print_info('loader', 'Building loader')
    
    # Get files involved
    src_files = get_all_files(arch_dir + 'loader/', None)
    target_file = bin_dir + 'tdlrldr.bin'
    
    # Assembly start section
    direct_build_files(
        files = [ arch_dir + 'loader/start.asm' ],
        target_name = obj_dir + 'loader/start.bin',
        ext_dep = None,
        tools = arch_tools['boot_tools']
    )
    
    # Real mode section
    build_files(
        files = [ arch_dir + 'loader/real.c' ],
        target_name = obj_dir + 'loader/real.elf',
        ext_dep = [ arch_dir + 'loader/real.ld' ],
        ext_flags = { 'ld/script' : arch_dir + 'loader/real.ld' },
        tools = arch_tools['boot_tools']
    )
    gen_bin(
        src_name = obj_dir + 'loader/real.elf',
        target_name = obj_dir + 'loader/real.bin',
        tools = arch_tools['boot_tools']
    )
    
    # Protected mode section
    build_files(
        files = [ arch_dir + 'loader/protected.c' ],
        target_name = obj_dir + 'loader/protected.elf',
        ext_dep = [ arch_dir + 'loader/protected.ld' ],
        ext_flags = { 'ld/script' : arch_dir + 'loader/protected.ld' },
        tools = arch_tools['boot_tools']
    )
    gen_bin(
        src_name = obj_dir + 'loader/protected.elf',
        target_name = obj_dir + 'loader/protected.bin',
        tools = arch_tools['boot_tools']
    )
    
    # Concatinate the sections
    cat_files(
        files = [ \
            obj_dir + 'loader/start.bin',
            obj_dir + 'loader/real.bin',
            obj_dir + 'loader/protected.bin',
        ],
        target_name = target_file,
        tools = arch_tools['boot_tools']
    )
    
def build_hal():
    print_info('hal', 'Building HAL')
    
    generic_files = get_all_files(src_dir + 'hal/', [ '.c' ])
    arch_files = get_all_files(arch_dir + 'hal/', [ '.c', '.asm', '.s', '.S' ])
    
    build_files(
        generic_files + arch_files,
        bin_dir + 'tdlrhal.bin',
        ext_flags = { 'ld/ext' : '-Ttext 0xFFF88000' },
    )
    
    #build_dir(
        #arch_dir + 'hal/', [ '.c', '.asm' ],
        #bin_dir + 'tdlrhal.bin',
        #ext_flags = { 'ld/ext' : '-Ttext 0xFFF88000' },
    #)
        
def build_arch():
    # Build boot
    if 'build_boot' in arch_funcs:
        arch_funcs['build_boot']()
    
    # Build loader
    if 'build_loader' in arch_funcs:
        arch_funcs['build_loader']()
    
    # Build HAL
    if 'build_hal' in arch_funcs:
        arch_funcs['build_hal']()
    
def build_disk():
    print_info('floppyimg', 'Building floppy image')
    
    if not os.path.exists(img_dir):
        os.makedirs(img_dir)
    
    # Files
    src_files = [ \
        bin_dir + 'boot/tdlrboot.fp',
        bin_dir + 'tdlrldr.bin',
        bin_dir + 'tdlrcore.img',
    ]
    target_name = img_dir + 'floppy.img'
    
    # Check if we need to rebuild the img
    regenerate = False
    for f in src_files:
        if need_build(f, target_name):
            regenerate = True
            break
        
    if not regenerate:
        return
    
    # Compose the cmd
    cmd = tools_bin_dir + 'floppyimg ' + target_name
    for f in src_files:
        cmd += ' ' + f
        
    # Execute the cmd
    code = exec_cmd(cmd)
    assert(code == 0)
    
    # Update record
    record_update(target_name)

def qemu8():
    print_info('emulator', 'Starting SMP QEMU')
    
    img_name = img_dir + 'floppy.img'
    
    # Compose the cmd
    cmd = 'qemu-system-i386' + \
        ' -m 512' + \
        ' -no-shutdown -no-reboot -no-kvm' + \
        ' -smp cores=2,threads=2,sockets=2' + \
        ' -drive if=floppy,format=raw,file=' + img_name
    
    # Execute the cmd
    code = exec_cmd(cmd)
    assert(code == 0)
    
def qemu():
    print_info('emulator', 'Starting QEMU')
    
    img_name = img_dir + 'floppy.img'
    
    # Compose the cmd
    cmd = 'qemu-system-i386' + \
        ' -m 512' + \
        ' -no-shutdown -no-reboot -no-kvm' + \
        ' -smp cores=1,threads=1,sockets=1' + \
        ' -drive if=floppy,format=raw,file=' + img_name
    
    # Execute the cmd
    code = exec_cmd(cmd)
    assert(code == 0)
    
def bochs():
    print_info('emulator', 'Starting Bochs')
    
    # Compose the cmd
    img_name = img_dir + 'floppy.img'
    bochs_dir = vm_dir + 'bochs/'
    cmd = 'cd ' + bochs_dir + ' && bochs -f ' + bochs_dir + 'bochsrc -q -log ' + bochs_dir + 'bochslog.txt -rc ' + bochs_dir + 'bochscmd;'
        
    # Execute the cmd
    code = exec_cmd(cmd)
    assert(code == 0)
    
def start_emu():
    emu_type = 'qemu'
    if emu_type in arch_funcs:
        arch_funcs[emu_type]()
    

# Setup global tools
arch_tools['global_tools'] = global_tools

# Setup arch tools
arch_tools['boot_tools'] = boot_tools

# Setup callback functions
arch_funcs['build_arch'] = build_arch
arch_funcs['build_disk'] = build_disk

arch_funcs['build_boot'] = build_boot
arch_funcs['build_boot_fp'] = build_boot_fp
arch_funcs['build_loader'] = build_loader
arch_funcs['build_hal'] = build_hal

arch_funcs['qemu'] = qemu
arch_funcs['qemu8'] = qemu8
arch_funcs['bochs'] = bochs
arch_funcs['start_emu'] = start_emu
